/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.plechinger.mcremote.server;

import com.plechinger.mcremote.client.ClientSettings;
import com.plechinger.mcremote.client.Connector;
import com.plechinger.mcremote.security.SecurityUtil;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.NoSuchPaddingException;

/**
 *
 * @author Lukas
 */
public class BasicServer {

    private ServerSocket server = null;
    private ServerThread st = null;
    private static final Logger LOG = Logger.getLogger(BasicServer.class.getName());

    public BasicServer(int port) throws IOException {
        server = new ServerSocket(port);//Erzeugen Serversocket
        server.setSoTimeout(1000); //1000 millisekunden, dh as accept wird alle 1000 millisekunden unterbrochen

    }

    private void log(String logText) {
        log(logText, Level.INFO);
    }

    private void log(String logText, Level level) {
        LOG.log(level, logText);
    }

    public void startServer() {
        if (st == null || !st.isAlive()) {
            st = new ServerThread(); //erzeugt einen neuen ServerThread
            st.start();
            log("server waiting on port" + server.getLocalPort() + "...", Level.INFO);
        }
    }

    public void stoppServer() {
        if (st != null || st.isAlive()) {
            st.interrupt();
            st = null; //auf null setzen damit man ihn wieder anstarten kann
            log("Server stopp", Level.INFO);
        }
    }

    class ServerThread extends Thread {

        public ServerThread() {
            this.setPriority(Thread.MIN_PRIORITY);

        }

        @Override
        public void run() {
            while (!this.isInterrupted()) {
                Socket socket;
                try {
                    socket = server.accept(); //alle 500 ms wird accept unterbrochen
                    log("server connectet to" + socket.getRemoteSocketAddress().toString(), Level.FINE);
                    ClientCommunicationThread cct = new ClientCommunicationThread(socket);
                    cct.start();
                } catch (SocketTimeoutException e) {
                    //log("server timeout");
                } catch (IOException ex) {
                }

            }
        }
    }

    class ClientCommunicationThread extends Thread {

        private Socket socket;

        public ClientCommunicationThread(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            InputStream is = null;
            OutputStream os = null;
            try {
                is = socket.getInputStream();
                os = socket.getOutputStream();

                is = new DataInputStream(is);
                os = new DataOutputStream(os);

                /*Key k = ClientSettings.getSettings().getEncryptionKey();
                try {
                    is = SecurityUtil.getCipherInputStream(is, k);
                    os = SecurityUtil.getCipherOutputStream(os, k);
                } catch (NoSuchAlgorithmException ex) {
                    Logger.getLogger(Connector.class.getName()).log(Level.SEVERE, null, ex);
                } catch (NoSuchPaddingException ex) {
                    Logger.getLogger(Connector.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvalidKeyException ex) {
                    Logger.getLogger(BasicServer.class.getName()).log(Level.SEVERE, null, ex);
                }*/


                ObjectInputStream ois = new ObjectInputStream(is);
                ObjectOutputStream oos = new ObjectOutputStream(os);

                Object request = ois.readObject();
                Object answer = processRequest(request);
                oos.writeObject(answer);
                oos.flush();

                oos.close();
                ois.close();
            } catch (IOException ex) {
                ex.printStackTrace();
                log("Communication problem with client: " + socket.getRemoteSocketAddress(), Level.SEVERE);

            } catch (ClassNotFoundException ex) {
                log("Communication problem with client: " + socket.getRemoteSocketAddress() + "class not found", Level.SEVERE);
            } finally {
                try {
                    is.close();
                    os.close();
                    socket.close();
                } catch (IOException ex) {
                    log("Communication problem with client: " + socket.getRemoteSocketAddress(), Level.SEVERE);
                }

            }
        }
    }

    protected Object processRequest(Object request) {

        return "request recevied: " + request.toString();
    }

    /*
     * public static void main(String[] args) throws IOException { BasicServer
     * bs;
     *
     * bs = new BasicServer(1337); bs.startServer(); /*try { Thread.sleep(5000);
     * } catch (InterruptedException ex) {
     * Logger.getLogger(BasicServer.class.getName()).log(Level.SEVERE, null,
     * ex); }
     *
     * //bs.stoppServer(); }
     */
}
